package com.jiangyg.mall.gateway.support.security.handler;

import com.jiangyg.mall.core.support.restful.Result;
import com.jiangyg.mall.core.utils.Logger;
import com.jiangyg.mall.core.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 类描述：认证异常相关处理
 *
 * @author jiangyg
 * @version 4.0
 * @date 2021-10-09
 */
@Slf4j
public class AuthErrorExceptionHandler implements ServerAuthenticationEntryPoint {

    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
        return Mono.defer(() -> Mono.just(exchange.getResponse()))
                .flatMap(response -> {
                    if (log.isInfoEnabled()) {
                        Logger.info(log, () -> String.format("请求[%s]认证异常：", WebUtils.getRequestPath(exchange)), ex);
                    }
                    final String errcode = ex instanceof CredentialsExpiredException ? "422" : "421";
                    final String rd = Result.instance(errcode).toJSONString();
                    response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
                    DataBuffer buffer = response.bufferFactory().wrap(rd.getBytes(StandardCharsets.UTF_8));
                    return response.writeWith(Mono.just(buffer)).doOnError(error -> DataBufferUtils.release(buffer));
                });
    }

}
